<!--
 * @Description: 
 * @Author: xuechengwu
 * @Email: xuechengwu@myhexin.com
 * @Date: 2021-08-10 16:17:54
 * @LastEditTime: 2021-08-10 20:11:15
 * @LastEditors: xuechengwu
-->
<template>
  <div class="polyline-container">
    <div class="editor-tool">
        <i class="iconfont icon-ic_pen" @click="onFinish" v-if="locked || editable"></i>
        <i class="iconfont icon-pingshenqueren" @click="onEdit" v-if="!locked"></i>
    </div>
    <div ref="container" class="polylin-canvas" >
        <svg height="100%" width="100%" preserveAspectRatio="none">
            <defs>
                <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
                <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
                <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
                </linearGradient>
            </defs>
            <path
                v-if="!locked && !editable"
                :d="points|join(enstyle, { toolX, toolY }, !locked, editable)"
                :style="{
                    fill: 'none',
                    stroke: `url(#grad1)`,
                    strokeWidth: strokeWidth,
                    'stroke-linecap': lineCap,
                    'stroke-dasharray': dasharray.length > 0 ? dasharray.join(',') : '',
                }"
            />
            <path
                v-if="locked || editable"
                :d="innerPoints|join(enstyle, { toolX, toolY }, !locked, editable)"
                :style="{
                    fill: 'none',
                    stroke: `url(#grad1)`,
                    strokeWidth: strokeWidth,
                    'stroke-linecap': lineCap,
                    'stroke-dasharray': dasharray.length > 0 ? dasharray.join(',') : '',
                }"
            />
            <template
                v-if="locked || editable"
            >
                <line
                    v-for="(item, index) in innerPoints"
                    :key="`line-0-${index}`"
                    :x1="item.S[0] * enstyle.width"
                    :y1="item.S[1] * enstyle.height"
                    :x2="item.C[0] * enstyle.width"
                    :y2="item.C[1] * enstyle.height"
                    style="stroke:#2a5caa;stroke-width:1"/>
                <line
                    v-for="(item, index) in innerPoints"
                    :key="`line-1-${index}`"
                    v-show="index > 0"
                    :x1="item.S[0] * enstyle.width"
                    :y1="item.S[1] * enstyle.height"
                    :x2="(item.S[0] * 2 - item.C[0]) * enstyle.width"
                    :y2="(item.S[1] * 2 - item.C[1]) * enstyle.height"
                    style="stroke:#2a5caa;stroke-width:1"/>
            </template>
        </svg>
        <template
                v-if="locked || editable"
            >
            <div
                v-for="(item, index) in innerPoints"
                :key="index"
                class="bezier-edit-rect"
                @mousedown="positionDown($event, item)"
                :style="{
                    left: `${item.S[0] * enstyle.width - 5}px`,
                    top: `${item.S[1] * enstyle.height - 5}px`,
                }"
                />
            <div
                v-for="(item, index) in innerPoints"
                class="bezier-edit-circle"
                :style="{
                    left:  `${item.C[0] * enstyle.width - 5}px`,
                    top:   `${item.C[1] * enstyle.height - 5}px`,
                }"
                :key="`circle-0-${index}`"
                @mousedown="controlDown($event, item)"
                />
            <div
                class="bezier-edit-circle"
                v-for="(item, index) in innerPoints"
                :key="`circle-1-${index}`"
                v-show="index > 0"
                :style="{
                    left: `${(item.S[0] * 2 - item.C[0]) * enstyle.width - 5}px`,
                    top: `${(item.S[1] * 2 - item.C[1]) * enstyle.height - 5}px`,
                }"
                @mousedown="controlPairDown($event, item)"
                />
        </template>
    </div>
    
  </div>
</template>

<script>
import { getGuid } from '@/utils/common';
export default {
    props: {
        stroke: {
            type: String,
            default: 'black',
        },
        strokeWidth: {
            type: Number,
            default: 3,
        },
        points: {
            type: Array,
            default: () => [],
        },
        locked: {
            type: Boolean,
            default: false,
        },
        enstyle: {
            type: Object,
            default: () => ({}),
        },
        editable: {
            type: Boolean,
            default: true,
        },
        lineCap: {
            type: String,
            default: 'butt',
        },
        dasharray: {
            type: Array,
            default: () => [],
        },
    },
    filters: {
        join(data, enstyle, point, bool, editable) {
            const { width, height, left, top } = enstyle;
            const { toolX, toolY } = point;
            if (data.length > 0) {
                const points = data.slice(1);
                const s = points.map(vo => 
                    `${(vo.S[0] * 2 - vo.C[0]) * width} ${(vo.S[1] * 2 - vo.C[1]) * height}, ${vo.S[0] * width} ${vo.S[1] * height}`
                );
                const bezier = s.join('S');
                const endPath = editable ? '' : `S ${toolX * width} ${toolY * height} ${toolX * width} ${toolY * height}`;
                if (!bool) {
                    return `M ${data[0].S[0] * width} ${data[0].S[1] * height} ${bezier === '' ? '' : `C ${data[0].C[0] * width} ${data[0].C[1] * height} ${bezier}`} ${endPath}`;
                } else {
                    return `M ${data[0].S[0] * width} ${data[0].S[1] * height} ${bezier === '' ? '' : `C ${data[0].C[0] * width} ${data[0].C[1] * height} ${bezier}`}`;
                }
            } else {
                return '';
            }
        }
    },
    data() {
        return {
            innerPoints: [],
            toolX: 0,
            toolY: 0,
            status: 'S',
            selectedPoint: null,
            selectedControl: null,
            selectedControlPair: null,
            finish: false,
        };
    },
    mounted() {
        this.innerPoints = this.points;
        if (this.locked) {
            this.$refs.container.addEventListener('mousedown', (e) => {
                if (this.editable || !this.locked || this.finish) {
                    return;
                }
                const { clientX, clientY } = e;
                const box = this.$refs.container.getBoundingClientRect();
                const { width, height } = box;
                const x = (clientX - box.left) / width;
                const y = (clientY - box.top) / height;
                if (this.status === 'S') {
                    const { innerPoints = [] } = this;
                    if (innerPoints.length === 0) {
                        this.innerPoints.push({
                            id: getGuid(),
                            S: [x, y],
                            C: [x, y],
                        });
                        this.status = 'C';
                    } else {
                        const targetS = innerPoints[innerPoints.length - 1].S;
                        const completed = ((targetS[0] - x) * (targetS[0] - x) * width * width + (targetS[1] - y) * (targetS[1] - y) * height * height) < 100;
                        if (completed) {
                            this.$emit('event', { event: 'ok', value: this.innerPoints });
                        } else {
                            this.innerPoints.push({
                                id: getGuid(),
                                S: [x, y],
                                C: [x, y],
                            });
                            this.status = 'C';
                        }
                    }
                } else {  
                    this.innerPoints[innerPoints.length - 1].C = [x, y];
                }       
            });
            this.$refs.container.addEventListener('mousemove', (e) => {
                if (!this.locked || this.finish) {
                    return;
                }
                const { clientX, clientY } = e;
                const box = this.$refs.container.getBoundingClientRect();
                const { width, height } = box;
                const x = (clientX - box.left) / width;
                const y = (clientY - box.top) / height;
                if (!this.editable) {
                    if (this.status === 'C') {
                        const { innerPoints = [] } = this;
                        innerPoints[innerPoints.length - 1].C = [x, y];
                    } else {
                        this.toolX = x;
                        this.toolY = y;
                    }
                } else {
                    if (this.selectedPoint != null) {
                        const distX = x - this.selectedPoint.S[0];
                        const distY = y - this.selectedPoint.S[1];
                        this.selectedPoint.S = [x, y];
                        const { C } = this.selectedPoint;
                        this.selectedPoint.C = [C[0] + distX, C[1] + distY];
                    } else if (this.selectedControl != null) {
                        this.selectedControl.C = [x, y];
                    } else if (this.selectedControlPair != null) {
                        const { C, S } = this.selectedControlPair;
                        this.selectedControlPair.C = [S[0] * 2 - x, S[1] * 2 - y];
                    }
                }
                
            });
            this.$refs.container.addEventListener('mouseup', (e) => {
                this.status = 'S';
                this.selectedPoint = null;
                this.selectedControl = null;
                this.selectedControlPair = null;
            });
        } 
        
    },
    methods: {
        reback(e) {
            e.stopPropagation();
            this.innerPoints.pop();
        },
        // finish(e) {
        //     console.log('ee===>', e);
        //     e.stopPropagation();
        //     console.log('finish');
        //     this.$emit('event', { event: 'ok', value: this.innerPoints });
        // },
        // onEditable(e) {
        //     e.stopPropagation();
        //     console.log('click===>', e);
        //     // this.$emit('event', { event: 'doEditable', value: { editable: true, locked: true }});
        // },
        positionDown(e, point) {
            e.stopPropagation();
        //    this.$emit('event', { event: 'doEditable', value: { editable: true, locked: true }});
            this.selectedPoint = point;
            this.selectedControl = null;
            this.selectedControlPair = null;
        },
        onFinish(e) {
            e.stopPropagation();
            this.finish = true;
            this.$emit('event', { event: 'doEditable', value: { editable: false, locked: false }});
            this.selectedPoint = null;
            this.selectedControl = null;
            this.selectedControlPair = null;
        },
        onEdit(e) {
            e.stopPropagation();
            this.finish = false;
            this.$emit('event', { event: 'doEditable', value: { editable: true,  locked: true }});
        },
        controlDown(e, point) {
            e.stopPropagation();
            this.selectedPoint = null;
            this.selectedControl = point;
            this.selectedControlPair = null;
        },
        controlPairDown(e, point) {
            e.stopPropagation();
            this.selectedPoint = null;
            this.selectedControl = null;
            this.selectedControlPair = point;
        },
        completeDraw(index) {
            if (this.innerPoints.length - 1 === index) {
                this.$emit('event', { event: 'ok', value: this.innerPoints });
            }
        }
    }
}
</script>

<style lang="less" scoped>
.polyline-container {
    width: 100%;
    height: 100%;
    cursor: crosshair;
    position: relative;
    .polylin-canvas{
        width: 100%;
        height: 100%;
    }
    .editor-tool {
        position: absolute;
        right: 0;
        top: 0;
        display: inline-block;
        z-index: 108;
    }
    .polyline-tool-box{
        right: 0;
        position: absolute;
        display: inline-block;
        cursor: pointer;
    }
    .bezier-edit-circle {
        display: inline-block;
        width: 10px;
        height: 10px;
        position: absolute;
        border: solid 1px #2a5caa;
        border-radius: 100%;
    }
    .bezier-edit-rect {
        display: inline-block;
        width: 10px;
        height: 10px;
        position: absolute;
        border: solid 1px #2a5caa;
    }
}
</style>
